package com.html.blog.controller;

import com.html.blog.interceptor.BlogInterceptor;
import com.html.blog.validator.BlogValidator;
import com.html.blog.model.Blog;
import com.jfinal.aop.Before;
import com.jfinal.core.Controller;

import lombok.extern.slf4j.Slf4j;

/**
 * BlogController
 * 所有 sql 写在 Model 或 Service 中，不要写在 Controller 中，养成好习惯，有利于大型项目的开发与维护
 *
 * Controller 是 JFinal 核心类之一，该类作为 MVC 模式中的控制器。
 * 基于 JFinal 的 Web 应用的控制器需要继承该类。
 * Controller 是定义 Action 方法的地点，是组织 Action 的一种方式，一个 Controller 可以包含多个 Action。
 * Controller 是线程安全的。
 */
@Slf4j
@Before(BlogInterceptor.class)
public class BlogController extends Controller {

	/**
	 * Controller 以及在其中定义的 public 无参方法称为一个 Action。
	 * Action 是请求的最小单位。
	 * Action 方法必须在 Controller 中声明，该方法必须是 public 可见性且没有形参。
	 */
	public void index() {
		setAttr("blogPage", Blog.me.paginate(getParaToInt(0, 1), 10));

		/**
		 * render 系列方法：
		 * render 系列方法将渲染不同类型的视图并返回给客户端。
		 * JFinal 目前支持的视图类型有：FreeMarker、JSP、Velocity、JSON、File、Text、Html 等等。
		 * 除了 JFinal 支持的视图型以外，还可以通过继承 Render 抽象类来无限扩展视图类型。
		 *
		 * 通常情况下使用 Controller.render(String)方法来渲染视图，
		 * 使用 Controller.render(String)时的视图类型由 JFinalConfig.configConstant(Constants constants) 配置中的constants.setViewType(ViewType)来决定，
		 * 该设置方法支持的 ViewType 有：FreeMarker、JSP、Velocity，不进行配置时的缺省配置为 FreeMarker。
		 *
		 * 假 设 在 JFinalConfig.configRoute(Routes routes) 中 有 如 下 Controller 映 射 配 置 ：
		 * routes.add(“/user”, UserController.class, “/path”)， render(String view)使用例子：
		 * render(”test.html”)  渲染名为 test.html 的视图，该视图的全路径为”/path/test.html”
		 * render(”/other_path/test.html”) 渲染名为 test.html 的视图，该视图的全路径为”/other_path/test.html”，即当参数以”/”开头时将采用绝对路径。
		 * renderFreeMarker(”test.html”) 渲染名为 test.html 的视图，且视图类型为FreeMarker。
		 * renderJsp(”test.html”)  渲染名为 test.html 的视图，且视图类型为 Jsp。
		 * renderVelocity(“test.html”)  渲染名为test.html 的视图，且视图类型为 Velocity。
		 * renderJson()  将所有通过 Controller.setAttr(String, Object)设置的变量转换成 json 数据并渲染。
		 * renderJson(“users”, userList)  以”users”为根，仅将 userList 中的数据转换成 json 数据并渲染。
		 * renderJson(user)  将 user 对象转换成 json 数据并渲染。
		 * renderJson(“{\”age\”:18}” )  直接渲染 json 字符串。
		 * renderJson(new String[]{“user”, “blog”}) 仅将 setAttr(“user”, user)与 setAttr(“blog”, blog)设置的属性转换成 json 并渲染。使用 setAttr 设置的其它属性并不转换为 json。
		 * renderFile(“test.zip”);  渲染名为 test.zip 的文件，一般用于文件下载
		 * renderText(“Hello JFinal”)  渲染纯文本内容”Hello JFinal”。
		 * renderHtml(“Hello Html”)  渲染 Html 内容”Hello Html”。
		 * renderError (404 , “test.html”) 渲染名为 test.html 的文件，且状态为 404。
		 * renderError (500 , “test.html”) 渲染名为 test.html 的文件，且状态为 500。
		 * renderNull()  不渲染，即不向客户端返回数据。
		 * render(new XmlRender())  使用自定义的 XmlRender 来渲染。
		 *
		 * 注意：
		 * 1. IE 不支持 contentType 为 application/json,在 ajax 上传文件完成后返回 json 时 IE 提示下载文件,
		 *    解决办法是使用：render(new JsonRender(params).forIE())。
		 * 2. 除 renderError 方法以外，在调用 render 系列的方法后程序并不会立即返回，如果需要立即返回需要使用 return 语句。
		 *    在一个 action 中多次调用 render 方法只有最后一次有效。
		 *
		 */
		render("blog.html");
	}

	/**
	 * getPara系列方法分为两种类型：
	 * 第 一 种 类 型 为 第 一 个 形 参 为 String 的 getPara 系 列 方 法 。
	 * 该 系 列 方 法 是 对HttpServletRequest.getParameter(String  name) 的 封 装 ，
	 * 这 类 方 法 都 是 转 调 了HttpServletRequest.getParameter(String name)。
	 *
	 * 第二种类型为第一个形参为 int 或无形参的getPara 系列方法。
	 * 该系列方法是去获取 urlPara 中所带的参数值。
	 *
	 * getParaMap 与 getParaNames 分别对应 HttpServletRequest 的 getParameterMap 与 getParameterNames。
	 *
	 * 示例：
	 * getPara(”title”)     返回页面表单域名为“title”参数值
	 * getParaToInt(”age”)  返回页面表单域名为“age”的参数值并转为 int 型
	 * getPara(0)           返回 url 请求中的 urlPara 参数的第一个值，如 http://localhost/controllerKey/method/v0-v1-v2 这个请求将返回”v0”
	 * getParaToInt(1)      返回 url 请求中的urlPara参数的第二个值并转换成int 型，如 http://localhost/controllerKey/method/2-5-9 这个请求将返回 5
	 * getParaToInt(2)      如 http://localhost/controllerKey/method/2-5-N8  这个请求将返回 -8 。 注意：约定字母 N 与 与 n  可以表示负号，这对 urlParaSeparator  为 “-”  时 非常有用
	 * getPara()            返回 url 请求中的 urlPara 参数的整体值，如 http://localhost/controllerKey/method/v0-v1-v2 这个请求将返回”v0-v1-v2”
	 *
	 */
	public void add() {
	}
	
	@Before(BlogValidator.class)
	public void save() {
		getModel(Blog.class).save();
		redirect("/blog");
	}

	public void edit() {
		/**
		 * setAttr(String, Object)转调了 HttpServletRequest.setAttribute(String, Object)，
		 * 该方法可以将各种数据传递给 View 并在 View 中显示出来。
		 */
		setAttr("blog", Blog.me.findById(getParaToInt()));
	}
	
	@Before(BlogValidator.class)
	public void update() {
		getModel(Blog.class).update();
		redirect("/blog");
	}
	
	public void delete() {
		Blog.me.deleteById(getParaToInt());
		redirect("/blog");
	}

	/**
	 * getFile  文件上传：
	 * Controller 提供了 getFile 系列方法支持文件上传。
	 * 特别注意：如果客户端请求为 multipart request（form 表单使用了 enctype="multipart/form-data"），
	 * 那么必须先调用 getFile 系列方法才能使 getPara 系列方法正常工作，
	 * 因为 multipart request 需要通过 getFile 系列方法解析请求体中的数据，包括参数。
	 */

}


